#include "epoll_poller.h"
#include "channel.h"
#include "logger.h"

#include <cstring>
#include <cerrno>
#include <unistd.h>

// 未添加到Poller
const int kNew = -1; // channel index 默认-1
// 已添加
const int kAdded = 1;
// 已删除
const int kDeleted = 2;

EPollPoller::EPollPoller(EventLoop *loop)
    : Poller(loop), epollfd_(::epoll_create1(EPOLL_CLOEXEC)), events_(kInitEventListSize) {
    if (epollfd_ < 0) {
        LOG_FATAL("epoll_create error:%d \n", errno);
    }
}

EPollPoller::~EPollPoller() { ::close(epollfd_); }

Timestamp EPollPoller::poll(int timeout_ms, ChannelList *active_channels) {
    LOG_INFO("func = %s => fd total count : %lu \n", __FUNCTION__, channels_.size());
    // 这里用LOG_DEBUG更好
    int num_events = ::epoll_wait(epollfd_, &*events_.begin(), static_cast<int>(events_.size()),
                                  timeout_ms); // 这里的&*events.begin()这个是首元素的地址
    int save_errno = errno;
    Timestamp now(Timestamp::now());

    if (num_events > 0) {
        LOG_INFO("%d events happened \n", num_events);
        fill_active_channels(num_events, active_channels);
        if (num_events == events_.size()) {
            events_.resize(events_.size() * 2);
        }
    } else if (num_events == 0) {
        LOG_DEBUG("%s timeout! \n", __FUNCTION__);
    } else {
        if (save_errno != EINTR) {
            errno = save_errno;
            LOG_ERROR("EPollPoller::poll() err!");
        }
    }

    return now;
}

// Channel update remove => EventLoop updateChannel removeChannel => Poller update... remove ...
void EPollPoller::update_channel(Channel *channel) {
    const int index = channel->index();
    LOG_INFO("func=%s => fd=%d events=%d index=%d \n", __FUNCTION__, channel->fd(),
             channel->events(), index);

    if (index == kNew || index == kDeleted) {
        if (index == kNew) {
            int fd = channel->fd();
            channels_[fd] = channel;
        }

        channel->set_index(kAdded);
        update(EPOLL_CTL_ADD, channel);
    } else {
        if (channel->is_none_event()) {
            update(EPOLL_CTL_DEL, channel);
            channel->set_index(kDeleted);
        } else {
            update(EPOLL_CTL_MOD, channel);
        }
    }
}
// Poller删除channel
void EPollPoller::remove_channel(Channel *channel) {
    int fd = channel->fd();
    channels_.erase(fd);
    LOG_INFO("func=%s => fd=%d \n", __FUNCTION__, fd);

    int index = channel->index();
    if (index == kAdded) {
        update(EPOLL_CTL_DEL, channel);
    }
    channel->set_index(kNew);
}
void EPollPoller::fill_active_channels(int num_events, ChannelList *active_channels) const {
    for (int i = 0; i < num_events; ++i) {
        Channel *channel = static_cast<Channel *>(events_[i].data.ptr);
        channel->set_revents(events_[i].events);
        active_channels->push_back(
            channel); // EventLoop 就拿到了它的poller给他的返回所有发生事件的channel列表了
    }
}
// 更新channel通道 epoll_ctl add/mod/del
void EPollPoller::update(int operation, Channel *channel) {
    epoll_event event;
    bzero(&event, sizeof event);
    event.events = channel->events();
    event.data.ptr = channel;
    int fd = channel->fd();

    if (::epoll_ctl(epollfd_, operation, fd, &event) < 0) {
        if (operation == EPOLL_CTL_DEL) {
            LOG_ERROR("epoll_ctl del error:%d \n", errno);
        } else {
            LOG_FATAL("epoll_ctl add/mod error:%d \n", errno);
        }
    }
}
